package com.my.study.nio.buffer;

import org.junit.Test;

import java.nio.ByteBuffer;

/**
 * @author Carlos
 * @version 1.0
 * @Description 缓冲区Buffer：在java NIO中负责数据的存取。缓冲区就是数组，用于存储不同类型的数据
 *
 * <P>
 *     ByteBuffer
 *     CharBuffer
 *     ShortBuffer
 *     IntBuffer
 *     LongBuffer
 *     FloatBuffer
 *     DoubleBuffer
 * </P>
 *
 * <p>
 *   API:
 *       allocate(int capacity): 分配一个指定大小的缓存区
 *
 * <p>
 *     缓冲区4个核心属性：mark <= position <= limit <= capacity
 *
 *     capacity: 容量，表示缓冲区最大存储数据容量，一旦声明，不能改变
 *     limit: 限制/界限，表示缓冲区中可以操作数据的大小。也就是，limit后面的数据不能进行读写操作
 *     position:位置，表示缓冲区中正在操作数据的位置
 *     mark: 标记，记录当前position位置。可以通过reset()把现在的position恢复到mark的位置
 * </p>
 *
 * <p>
 *     直接缓冲区和非直接缓冲区
 *
 *     1、非直接缓冲区：通过allocate()方法分配缓冲区，将缓冲区建立在JVM中
 *     2、直接缓冲区：通过allocateDirect()分配直接缓冲区，将缓冲区建立在物理内存中
 *
 * </p>
 *
 * @date 2021/7/31 10:20
 **/
public class BufferTest {


    @Test
    public void test01() {

        String str = "abcde";

        // 分配一个1024大小的缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        System.out.println("==========allocate()============");
        System.out.println("capacity= " + buffer.capacity());
        System.out.println("limit= " + buffer.limit());
        System.out.println("position= " + buffer.position());
        System.out.println("mark= " + buffer.mark());

        // 写模式
        buffer.put(str.getBytes());
        System.out.println("==========put()============");
        System.out.println("capacity= " + buffer.capacity());
        System.out.println("limit= " + buffer.limit());
        System.out.println("position= " + buffer.position());
        System.out.println("mark= " + buffer.mark());

        // 切换到读模式
        buffer.flip();
        System.out.println("==========flip()============");
        System.out.println("capacity= " + buffer.capacity());
        System.out.println("limit= " + buffer.limit());
        System.out.println("position= " + buffer.position());
        System.out.println("mark= " + buffer.mark());

        byte[] dst = new byte[buffer.limit()];
        buffer.get(dst);
        System.out.println(new String(dst, 0, dst.length));
        System.out.println("==========get()============");
        System.out.println("capacity= " + buffer.capacity());
        System.out.println("limit= " + buffer.limit());
        System.out.println("position= " + buffer.position());
        System.out.println("mark= " + buffer.mark());


        // 可重复读数据
        buffer.rewind();
        System.out.println("==========rewind()============");
        System.out.println("capacity= " + buffer.capacity());
        System.out.println("limit= " + buffer.limit());
        System.out.println("position= " + buffer.position());
        System.out.println("mark= " + buffer.mark());


        // 清空缓冲区，回到最开始状态，但是里面的数据没有被清空，只是不知道位置如何了，变成了"被遗忘"状态了
        buffer.clear();
        System.out.println("==========clear()============");
        System.out.println("capacity= " + buffer.capacity());
        System.out.println("limit= " + buffer.limit());
        System.out.println("position= " + buffer.position());
        System.out.println("mark= " + buffer.mark());
    }

    /**
     * 测试mark()方法 、reset()方法联合使用
     */
    @Test
    public void test02() {
        String str = "abcde";
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        //写入缓冲区
        buffer.put(str.getBytes());

        //切换为读模式
        buffer.flip();

        byte[] dst = new byte[buffer.limit()];
        buffer.get(dst, 0, 2);
        System.out.println(new String(dst, 0, 2));
        System.out.println(buffer.position());

        // 记录此时的position位置
        // 此时，position=2，执行完，mark=position=2
        buffer.mark();

        // 再次读取数据
        buffer.get(dst, 2, 2);
        System.out.println(new String(dst, 0, 2));
        System.out.println(buffer.position());

        // 把position恢复到mark标记的位置
        buffer.reset();
        System.out.println(buffer.position());



        // 判断缓冲区中是否还有数据
        if (buffer.hasRemaining()) {
            // 剩余
            System.out.println(buffer.remaining());
        }

    }


    @Test
    public void test03() {
        ByteBuffer direct = ByteBuffer.allocateDirect(1024);

        boolean isDirect = direct.isDirect();


    }
}

